#ifndef FILE_SE_System_HPP
#define FILE_SE_System_HPP


/********************************************//**
 * \brief Log as the program passes by it.
 * 
 * Guaranteed to be writen in order of execution.
 ***********************************************/
#define SE_TRACE {\
                 std::string s("At line "QUOTEME(__LINE__)" in file "QUOTEME(__FILE__));\
                 se::System::trace->Write(s);\
                 }

/********************************************//**
 * \brief Log some data to the trace
 *
 * Uses the << syntax. Example :
 * 
 * \code
 * SE_LOG(INFO,"Reached the "<<checkpointName<<" with score "<<score<<".")
 * \endcode
 *
 * You musn't use the namespace before the log type.
 *
 * \attention The write order is not guaranteed to be chronological.
 *
 * \param logType The logging type without the namespace.
 * \param data The stream (view example).
 * \see SE_LOGC
 ***********************************************/
#define SE_LOG(logType,data) {\
                             std::stringstream ss;\
                             {ss<<data;}\
                             ::se::System::trace->Write(se::System::Trace::logType,(ss.str()).c_str());\
                             }

/********************************************//**
 * \brief Log some data to the trace, guaranteed.
 *
 * Same as SE_LOG, but with the guarantee that the logging info will be in order,
 * and will be written if the program crashes.
 *
 * \attention Because of the guarantee it gives, the macro is way slower,
 * because it need to wait for the complete writing of all the content.
 * If the additional functionnality is not needed, use SE_LOG
 *
 * See SE_LOG for syntax.
 *
 * \param logType The logging type without the namespace.
 * \param data The stream (view example).
 * \see SE_LOG
 ***********************************************/
#define SE_LOGC(logType,data) {\
                              std::stringstream ss;\
                              {ss<<data;}\
                              se::System::trace->Write(se::System::Trace::logType,ss.str().c_str());\
                              }

#include "Types.hpp"

namespace se{

class System{
	
	public:
		class Chrono;
		class GTime;
		
		class Trace;
		class Exception;
		class ExceptionSafeThread;
		class InterruptibleThread;
		
		template<typename t> class ProducerConsumerSwap;
		
		static GTime* time;
		static Trace* trace;

		/********************************************//**
		 * A signal variable.
		 * 
		 * The use is to set it to false by default, and that the
		 * control thread and the thread itself have a reference
		 * on it. 
		 * 
		 * When the control thread whishes to synchronyze, either
		 * for request the thread to exit, or to ask him to
		 * prepare itself to update soem parameters,
		 * it set it to true.
		 *
		 * This kind of use is lockless, but if the variable
		 * must be used several times, only one control-able thread
		 * must exist, else a more complicated system is mandatory.
		 *
		 * Summing up the uses :
		 * \li 1 control, 1 thread : multiple uses :
		 * control wait false, set - thread read, acts, unset.
		 * \li n control,1 thread : multiple uses, no count guarantee :
		 * control wait false, set - thread read, acts, unset.
		 * \li n control, n thread : one use :
		 * control set - thread read, acts.
		 *
		 * Of course, it can be used in more complex control
		 * schemes, but then the thinking must be done
		 * more toroughly.
		 ***********************************************/
		typedef volatile bool ThreadSignal_t;
};

}//</ namespace se>


#endif // FILE_SE_System_HPP
